/*
 * Copyright Notice. Copyright 2011 Northwestern University and Stanford
 * University (“caBIG® Participant”). AIM Template Enterprise Service conforms
 * to caBIG® technical specifications and is part of the caBIG® initiative. The
 * software subject to this notice and license includes human readable source
 * code form, machine readable, binary, object code form and related
 * documentation (the “caBIG® Software”).
 *
 * This caBIG® Software License (the “License”) is between the National Cancer
 * Institute (NCI) and You. “You (or “Your”) shall mean a person or an entity,
 * and all other entities that control, are controlled by, or are under common
 * control with the entity. “Control” for purposes of this definition means (i)
 * the direct or indirect power to cause the direction or management of such
 * entity, whether by contract or otherwise, or (ii) ownership of fifty percent
 * (50%) or more of the outstanding shares, or (iii) beneficial ownership of
 * such entity.
 *
 * Provided that You agree to the conditions described below, NCI grants You a
 * non-exclusive, worldwide, perpetual, fully-paid-up, no-charge, irrevocable,
 * transferable and royalty-free right and license in its rights in the caBIG®
 * Software, including any copyright or patent rights therein, to (i) use,
 * install, disclose, access, operate, execute, reproduce, copy, modify,
 * translate, market, publicly display, publicly perform, and prepare
 * derivative works of the caBIG® Software in any manner and for any purpose,
 * and to have or permit others to do so; (ii) make, have made, use, practice,
 * sell, and offer for sale, import, and/or otherwise dispose of caBIG®
 * Software (or portions thereof); (iii) distribute and have distributed to and
 * by third parties the caBIG® Software and any modifications and derivative
 * works thereof; and (iv) sublicense the foregoing rights set out in (i), (ii)
 * and (iii) to third parties, including the right to license such rights to
 * further third parties. For sake of clarity, and not by way of limitation,
 * NCI shall have no right of accounting or right of payment from You or Your
 * sublicensees for the rights granted under this License. This License is
 * granted at no charge to You. Your downloading, copying, modifying,
 * displaying, distributing or use of caBIG® Software constitutes acceptance of
 * all of the terms and conditions of this Agreement. If you do not agree to
 * such terms and conditions, you have no right to download, copy, modify,
 * display, distribute or use the caBIG® Software.
 *
 * Your redistributions of the source code for the caBIG® Software must retain
 * the above copyright notice, this list of conditions and the disclaimer and
 * limitation of liability of Article 6 below. Your redistributions in object
 * code form must reproduce the above copyright notice, this list of conditions
 * and the disclaimer of Article 6 in the documentation and/or other materials
 * provided with the distribution, if any.
 *
 * Your end-user documentation included with the redistribution, if any, must
 * include the following acknowledgment: “This product includes software
 * developed by Danny Korenblum, Alan Snyder, Vitaliy Semeshko, Vladimir Kleper
 * and Pattanasak Mongkolwat, Northwestern University and Stanford University.”
 * If You do not include such end-user documentation, You shall include this
 * acknowledgment in the caBIG® Software itself, wherever such third-party
 * acknowledgments normally appear.
 *
 * You may not use the names “Northwestern University”, “Stanford University”,
 * “The National Cancer Institute”, “NCI”, “Cancer Bioinformatics Grid” or
 * “caBIG®” to endorse or promote products derived from this caBIG® Software.
 * This License does not authorize You to use any trademarks, service marks,
 * trade names, logos or product names of either caBIG® Participant, NCI or
 * caBIG®, except as required to comply with the terms of this License.
 *
 * For sake of clarity, and not by way of limitation, You are not prohibited by
 * this License from incorporating this caBIG® Software into Your proprietary
 * programs and into any third party proprietary programs. However, if You
 * incorporate the caBIG® Software into third party proprietary programs, You
 * agree that You are solely responsible for obtaining any permission from such
 * third parties required to incorporate the caBIG® Software into such third
 * party proprietary programs and for informing Your sublicensees, including
 * without limitation Your end-users, of their obligation to secure any
 * required permissions from such third parties before incorporating the caBIG®
 * Software into such third party proprietary software programs. In the event
 * that You fail to obtain such permissions, You agree to indemnify NCI for any
 * claims against NCI by such third parties, except to the extent prohibited by
 * law, resulting from Your failure to obtain such permissions.
 * For sake of clarity, and not by way of limitation, You may add Your own
 * copyright statement to Your modifications and to the derivative works, and
 * You may provide additional or different license terms and conditions in
 * Your sublicenses of modifications of the caBIG® Software, or any derivative
 * works of the caBIG® Software as a whole, provided Your use, reproduction,
 * and distribution of the Work otherwise complies with the conditions stated
 * in this License.
 *
 * THIS caBIG® SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES (INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE) ARE
 * DISCLAIMED. IN NO EVENT SHALL NCI OR THE NORTHWESTERN UNIVERSITY OR ITS
 * AFFILIATES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS caBIG® SOFTWARE, EVEN
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package edu.stanford.isis.atb.domain.template;

import static org.apache.commons.collections.CollectionUtils.isEmpty;
import static org.apache.commons.collections.CollectionUtils.isNotEmpty;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import javax.validation.Valid;
import javax.validation.constraints.AssertTrue;
import javax.validation.constraints.NotNull;

import org.hibernate.validator.constraints.NotEmpty;
import org.simpleframework.xml.Attribute;
import org.simpleframework.xml.Element;
import org.simpleframework.xml.ElementList;
import org.simpleframework.xml.ElementUnion;
import org.simpleframework.xml.Root;
import org.simpleframework.xml.core.Commit;

/**
 * @author Vitaliy Semeshko
 */

@Root(name="Component", strict=false)
public class TemplateComponent extends AbstractRemovableElement {

	@Valid
	@Element(name="QuestionType", required=false)
	private QuestionType questionType;
	
	@Valid
	@NotNull(message = "{templateComponent.content.notNull}")
	@ElementUnion({
		@Element(name="AnatomicEntity", type=AnatomicEntity.class, required=false),
		@Element(name="ImagingObservation", type=ImagingObservation.class, required=false),
		@Element(name="Inference", type=Inference.class, required=false),
		@Element(name="GeometricShape", type=GeometricShape.class, required=false),
		@Element(name="Calculation", type=Calculation.class, required=false)})
	private RemovableElement content;
	
	@NotEmpty(message = "{templateComponent.label.notEmpty}")
	@Attribute(required=false)
	private String label;
	
	@Attribute(required=false)
	private int itemNumber;
	
	@Attribute(required=false)
	private String authors;
	
	@Attribute(required=false)
	private String explanatoryText;
	
	@Attribute(required=false)
	private long minCardinality;
	
	@Attribute(required=false)
	private long maxCardinality;

	@Attribute(required=false)
	private boolean shouldDisplay;

	@Attribute(required=false)
	private String groupLabel;
	
	@Valid
	@ElementList(name="AllowedTerm", inline=true, required=false)
	private List<AllowedTerm> allowedTerms;
	
	@SuppressWarnings("unused")
	@Commit
	private void afterPropertiesSet() {
		if (content != null) {
			content.setRemoveCommand(new RemoveCommand() {
				@Override
				public void execute() {
					content = null;
				}
			});
		}
		
		if (questionType != null) {
			questionType.setRemoveCommand(new RemoveCommand() {
				@Override
				public void execute() {
					questionType = null;
				}
			});
		}
		
		if (allowedTerms != null) {
			for (AllowedTerm allowedTerm : allowedTerms) {
				allowedTerm.initRemoveCommand(allowedTerms);
				allowedTerm.initContext(allowedTerms);
			}
		}
	}
	
	@AssertTrue(message = "{templateComponent.allowedTerms.notEmpty}")
	public boolean isAllowedTermsValidNotEmpty() {
		// allowed terms should not be empty
		if ((content instanceof AnatomicEntity) || (content instanceof ImagingObservation) || (content instanceof Inference)) {
			return isNotEmpty(allowedTerms);
		}
		return true;
	}
	
	@AssertTrue(message = "{templateComponent.allowedTerms.empty}")
	public boolean isAllowedTermsValidEmpty() {
		// allowed terms should be empty
		if ((content instanceof Calculation) || (content instanceof GeometricShape)) {
			return isEmpty(allowedTerms);
		}
		return true;
	}
	
	public RemovableElement getContent() {
		return content;
	}
	
	public void setContent(RemovableElement content) {
		this.content = content;
		content.setRemoveCommand(new RemoveCommand() {
			@Override
			public void execute() {
				TemplateComponent.this.content = null;
			}
		});
	}

	public String getLabel() {
		return label;
	}

	public void setLabel(String label) {
		this.label = label;
	}
	
	public int getItemNumber() {
		return itemNumber;
	}

	public void setItemNumber(int itemNumber) {
		this.itemNumber = itemNumber;
	}

	public String getAuthors() {
		return authors;
	}

	public void setAuthors(String authors) {
		this.authors = authors;
	}

	public String getExplanatoryText() {
		return explanatoryText;
	}

	public void setExplanatoryText(String explanatoryText) {
		this.explanatoryText = explanatoryText;
	}

	public long getMinCardinality() {
		return minCardinality;
	}

	public void setMinCardinality(long minCardinality) {
		this.minCardinality = minCardinality;
	}

	public long getMaxCardinality() {
		return maxCardinality;
	}

	public void setMaxCardinality(long maxCardinality) {
		this.maxCardinality = maxCardinality;
	}

	public boolean isShouldDisplay() {
		return shouldDisplay;
	}

	public void setShouldDisplay(boolean shouldDisplay) {
		this.shouldDisplay = shouldDisplay;
	}

	public String getGroupLabel() {
		return groupLabel;
	}

	public void setGroupLabel(String groupLabel) {
		this.groupLabel = groupLabel;
	}

	public QuestionType getQuestionType() {
		return questionType;
	}

	public void setQuestionType(QuestionType questionType) {
		this.questionType = questionType;
		questionType.setRemoveCommand(new RemoveCommand() {
			@Override
			public void execute() {
				TemplateComponent.this.questionType = null;
			}
		});
	}
	
	public Collection<AllowedTerm> getAllowedTerms() {
		if (allowedTerms == null) {
			return Collections.emptyList();
		}
		return allowedTerms;
	}

	public void addAllowedTerm(AllowedTerm allowedTerm) {
		if (allowedTerms == null) {
			allowedTerms = new ArrayList<AllowedTerm>();
		}
		allowedTerms.add(allowedTerm);
		allowedTerm.initRemoveCommand(allowedTerms);
		allowedTerm.initContext(allowedTerms);
	}
	
	public void clearAllowedTerms() {
		this.allowedTerms = null;
	}
	
	@Override
	public String toString() {
		return itemNumber + " - " + label;
	}
	
}
